#include "fxcc/core/graph/common/TextureLoader.h"
#include "fxcc/core/graph/common/GraphImpl.h"


std::unordered_map<std::string, std::shared_ptr<fxcc::graph::common::Texture2DJack>> TextureLoader::m_Texture2Ds;

std::unordered_map<std::string, std::shared_ptr<fxcc::graph::common::Texture3DJack>> TextureLoader::m_Texture3Ds;

std::unordered_map<std::string, std::shared_ptr<fxcc::graph::common::TextureCubeJack>> TextureLoader::m_TextureCubes;

std::unordered_map<std::string, std::shared_ptr<fxcc::graph::common::Texture2DArrayJack>> TextureLoader::m_Texture2DArrays;

std::unordered_map<std::string, std::shared_ptr<fxcc::graph::common::TextureCubeArrayJack>> TextureLoader::m_TextureCubeArrays;

std::unordered_map<std::string, std::shared_ptr<fxcc::graph::common::TextureCubeJack>>  TextureLoader::m_IrradianceMaps;

std::unordered_map<std::string, std::shared_ptr<fxcc::graph::common::TextureCubeJack>>  TextureLoader::m_PrefilterMapss;

std::unordered_map<std::string, std::shared_ptr<fxcc::graph::common::Texture2DJack>>  TextureLoader::m_BrdfTextureMaps;


bool TextureLoader::LoadFile(const fxcc::File& file)
{
    switch (file.m_FileType)
    {
    case fxcc::_DDS_:
        return LoadDDSFile(file);
    default:
        return false;
    }
}

bool TextureLoader::LoadDDSFile(const fxcc::File& file)
{
    fxcc::graph::common::Texture2DJack::Desc desc;
    if (!desc.SetDDS(file.m_RelativePath))
    {
        return false;
    }
    m_Texture2Ds[file.m_RelativePath] = fxcc::graph::common::GraphImpl::CreateTexture2D(desc);
    return m_Texture2Ds[file.m_RelativePath].get();

}

std::shared_ptr<fxcc::graph::common::Texture2DJack> TextureLoader::LoadDDS2DFile(const std::string& path)
{
    auto it = m_Texture2Ds.find(path);
    if (it != m_Texture2Ds.end())
    {
        return it->second;
    }

    fxcc::graph::common::Texture2DJack::Desc desc;
    if (desc.SetDDS(path))
    {
        auto inst = fxcc::graph::common::GraphImpl::CreateTexture2D(desc);
        m_Texture2Ds[path] = inst;
        return inst;
    }

    return false;
}

std::shared_ptr<fxcc::graph::common::Texture2DJack> TextureLoader::Load2DFile(const std::string& path)
{
    auto it = m_Texture2Ds.find(path);
    if (it != m_Texture2Ds.end())
    {
        return it->second;
    }

    fxcc::graph::common::Texture2DJack::Desc desc;
    if (desc.SetPath(path))
    {
        auto inst = fxcc::graph::common::GraphImpl::CreateTexture2D(desc);
        m_Texture2Ds[path] = inst;
        return inst;
    }

    return false;
}

std::shared_ptr<fxcc::graph::common::TextureCubeJack> TextureLoader::LoadPrefilterMap(const std::string& path)
{
    auto it = m_PrefilterMapss.find(path);
    if (it != m_PrefilterMapss.end())
    {
        return it->second;
    }
    fxcc::graph::common::TextureCubeJack::Desc desc;
    if (desc.SetDDS(path))
    {
        auto inst = fxcc::graph::common::GraphImpl::CreateTextureCube(desc);
        m_PrefilterMapss[path] = inst;
        return inst;
    }
    return std::shared_ptr<fxcc::graph::common::TextureCubeJack>();
}

std::shared_ptr<fxcc::graph::common::TextureCubeJack> TextureLoader::LoadIrradianceMap(const std::string& path)
{
    auto it = m_IrradianceMaps.find(path);
    if (it != m_IrradianceMaps.end())
    {
        return it->second;
    }
    fxcc::graph::common::TextureCubeJack::Desc desc;
    if (desc.SetDDS(path))
    {
        auto inst = fxcc::graph::common::GraphImpl::CreateTextureCube(desc);
        m_IrradianceMaps[path] = inst;
        return inst;
    }
    return std::shared_ptr<fxcc::graph::common::TextureCubeJack>();
}

std::shared_ptr<fxcc::graph::common::Texture2DJack> TextureLoader::LoadBrdfMap(const std::string& path)
{
    auto it = m_BrdfTextureMaps.find(path);
    if (it != m_BrdfTextureMaps.end())
    {
        return it->second;
    }
    fxcc::graph::common::Texture2DJack::Desc desc;

    if (desc.SetWIC(path, 3, 2))
    {
        auto inst = fxcc::graph::common::GraphImpl::CreateTexture2D(desc);
        m_BrdfTextureMaps[path] = inst;
        return inst;
    }
    return std::shared_ptr<fxcc::graph::common::Texture2DJack>();
}



std::shared_ptr<fxcc::graph::common::Texture2DArrayJack> TextureLoader::LoadDDS2DArrayFile(const std::string& path)
{
    auto it = m_Texture2DArrays.find(path);
    if (it != m_Texture2DArrays.end())
    {
        return it->second;
    }
    fxcc::graph::common::Texture2DArrayJack::Desc desc;
    if (desc.SetDDSPath(path))
    {
        auto inst = fxcc::graph::common::GraphImpl::CreateTexture2DArray(desc);
        m_Texture2DArrays[path] = inst;
        return inst;
    }
    return std::shared_ptr<fxcc::graph::common::Texture2DArrayJack>();
}

std::shared_ptr<fxcc::graph::common::TextureCubeJack> TextureLoader::LoadDDSCubeFile(const std::string& path)
{
    auto it = m_TextureCubes.find(path);
    if (it != m_TextureCubes.end())
    {
        return it->second;
    }
    fxcc::graph::common::TextureCubeJack::Desc desc;
    if (desc.SetDDS(path))
    {
        auto inst = fxcc::graph::common::GraphImpl::CreateTextureCube(desc);
        m_TextureCubes[path] = inst;
        return inst;
    }

    return std::shared_ptr<fxcc::graph::common::TextureCubeJack>();
}

std::shared_ptr<fxcc::graph::common::TextureCubeArrayJack> TextureLoader::LoadDDSCubeArrayFile(const std::string& path)
{
    auto it = m_TextureCubeArrays.find(path);
    if (it != m_TextureCubeArrays.end())
    {
        return it->second;
    }

    fxcc::graph::common::TextureCubeArrayJack::Desc desc;
    if (desc.SetDDS(path))
    {
        auto inst = fxcc::graph::common::GraphImpl::CreateTextureCubeArray(desc);
        m_TextureCubeArrays[path] = inst;
        return inst;
    }

    return std::shared_ptr<fxcc::graph::common::TextureCubeArrayJack>();
}

std::shared_ptr<fxcc::graph::common::Texture3DJack> TextureLoader::LoadDDS3DFile(const std::string& path)
{
    auto it = m_Texture3Ds.find(path);
    if (it != m_Texture3Ds.end())
    {
        return it->second;
    }
    fxcc::graph::common::Texture3DJack::Desc desc;
    if (desc.SetDDS(path))
    {
        auto inst = fxcc::graph::common::GraphImpl::CreateTexture3D(desc);
        m_Texture3Ds[path] = inst;
        return inst;
    }

    return std::shared_ptr<fxcc::graph::common::Texture3DJack>();
}

